package edu.cuny.baruch.cis9590.library.gui;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import org.apache.commons.codec.digest.DigestUtils;

import edu.cuny.baruch.cis9590.library.database.LoginDAO;
import edu.cuny.baruch.cis9590.library.database.PatronDAO;
import edu.cuny.baruch.cis9590.library.entities.Login;
import edu.cuny.baruch.cis9590.library.entities.Patron;

final class RegisterPanel extends LibraryPanel {

    private final JTextField addressField;
    private final JTextField cityField;
    private final LibraryGUI libraryGUI;
    private LoginDAO loginDAO;
    private final JTextField nameField;
    private final JPasswordField passwordField;
    private final PatronDAO patronDAO;
    private final JComboBox stateComboBox;
    private final JTextField usernameField;
    private final JTextField zipField;
    
    public RegisterPanel(LibraryGUI libraryGUI) {
        this.libraryGUI = libraryGUI;
        this.loginDAO = new LoginDAO();
        this.patronDAO = new PatronDAO();
        
        GridBagLayout gridBagLayout = new GridBagLayout();
        gridBagLayout.columnWidths = new int[]{0, 0, 0, 0, 0, 0, 0, 0};
        gridBagLayout.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        gridBagLayout.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
        gridBagLayout.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
        setLayout(gridBagLayout);
        
        JLabel nameLabel = new JLabel("Name");
        GridBagConstraints gbc_nameLabel = new GridBagConstraints();
        gbc_nameLabel.anchor = GridBagConstraints.EAST;
        gbc_nameLabel.insets = new Insets(0, 0, 5, 5);
        gbc_nameLabel.gridx = 1;
        gbc_nameLabel.gridy = 1;
        add(nameLabel, gbc_nameLabel);
        
        nameField = new JTextField();
        nameLabel.setLabelFor(nameField);
        GridBagConstraints gbc_nameField = new GridBagConstraints();
        gbc_nameField.gridwidth = 4;
        gbc_nameField.insets = new Insets(0, 0, 5, 5);
        gbc_nameField.fill = GridBagConstraints.HORIZONTAL;
        gbc_nameField.gridx = 2;
        gbc_nameField.gridy = 1;
        add(nameField, gbc_nameField);
        nameField.setColumns(20);
        
        JLabel addressLabel = new JLabel("Address");
        GridBagConstraints gbc_addressLabel = new GridBagConstraints();
        gbc_addressLabel.anchor = GridBagConstraints.EAST;
        gbc_addressLabel.insets = new Insets(0, 0, 5, 5);
        gbc_addressLabel.gridx = 1;
        gbc_addressLabel.gridy = 2;
        add(addressLabel, gbc_addressLabel);
        
        addressField = new JTextField();
        addressLabel.setLabelFor(addressField);
        GridBagConstraints gbc_addressField = new GridBagConstraints();
        gbc_addressField.gridwidth = 4;
        gbc_addressField.insets = new Insets(0, 0, 5, 5);
        gbc_addressField.fill = GridBagConstraints.HORIZONTAL;
        gbc_addressField.gridx = 2;
        gbc_addressField.gridy = 2;
        add(addressField, gbc_addressField);
        addressField.setColumns(20);
        
        JLabel cityLabel = new JLabel("City");
        GridBagConstraints gbc_cityLabel = new GridBagConstraints();
        gbc_cityLabel.anchor = GridBagConstraints.EAST;
        gbc_cityLabel.insets = new Insets(0, 0, 5, 5);
        gbc_cityLabel.gridx = 1;
        gbc_cityLabel.gridy = 3;
        add(cityLabel, gbc_cityLabel);
        
        cityField = new JTextField();
        GridBagConstraints gbc_cityField = new GridBagConstraints();
        gbc_cityField.gridwidth = 4;
        gbc_cityField.insets = new Insets(0, 0, 5, 5);
        gbc_cityField.fill = GridBagConstraints.HORIZONTAL;
        gbc_cityField.gridx = 2;
        gbc_cityField.gridy = 3;
        add(cityField, gbc_cityField);
        cityField.setColumns(20);
        
        JLabel stateLabel = new JLabel("State");
        GridBagConstraints gbc_stateLabel = new GridBagConstraints();
        gbc_stateLabel.anchor = GridBagConstraints.EAST;
        gbc_stateLabel.insets = new Insets(0, 0, 5, 5);
        gbc_stateLabel.gridx = 1;
        gbc_stateLabel.gridy = 4;
        add(stateLabel, gbc_stateLabel);
        
        stateComboBox = new JComboBox(new String[] {
            "AL","AK","AZ","AR","CA","CO","CT","DE","DC","FL","GA","HI","ID",
            "IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO",
            "MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA",
            "RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"});
        stateLabel.setLabelFor(stateComboBox);
        GridBagConstraints gbc_stateComboBox = new GridBagConstraints();
        gbc_stateComboBox.insets = new Insets(0, 0, 5, 5);
        gbc_stateComboBox.fill = GridBagConstraints.HORIZONTAL;
        gbc_stateComboBox.gridx = 2;
        gbc_stateComboBox.gridy = 4;
        add(stateComboBox, gbc_stateComboBox);
        
        JLabel zipLabel = new JLabel("Zip");
        GridBagConstraints gbc_zipLabel = new GridBagConstraints();
        gbc_zipLabel.anchor = GridBagConstraints.EAST;
        gbc_zipLabel.insets = new Insets(0, 0, 5, 5);
        gbc_zipLabel.gridx = 4;
        gbc_zipLabel.gridy = 4;
        add(zipLabel, gbc_zipLabel);
        
        zipField = new JTextField();
        zipLabel.setLabelFor(zipField);
        GridBagConstraints gbc_zipField = new GridBagConstraints();
        gbc_zipField.insets = new Insets(0, 0, 5, 5);
        gbc_zipField.fill = GridBagConstraints.HORIZONTAL;
        gbc_zipField.gridx = 5;
        gbc_zipField.gridy = 4;
        add(zipField, gbc_zipField);
        zipField.setColumns(5);
        
        JLabel usernameLabel = new JLabel("Username");
        GridBagConstraints gbc_usernameLabel = new GridBagConstraints();
        gbc_usernameLabel.anchor = GridBagConstraints.EAST;
        gbc_usernameLabel.insets = new Insets(0, 0, 5, 5);
        gbc_usernameLabel.gridx = 1;
        gbc_usernameLabel.gridy = 5;
        add(usernameLabel, gbc_usernameLabel);
        
        usernameField = new JTextField();
        usernameLabel.setLabelFor(usernameField);
        GridBagConstraints gbc_usernameField = new GridBagConstraints();
        gbc_usernameField.gridwidth = 4;
        gbc_usernameField.insets = new Insets(0, 0, 5, 5);
        gbc_usernameField.fill = GridBagConstraints.HORIZONTAL;
        gbc_usernameField.gridx = 2;
        gbc_usernameField.gridy = 5;
        add(usernameField, gbc_usernameField);
        usernameField.setColumns(20);
        
        JLabel passwordLabel = new JLabel("Password");
        passwordLabel.setLabelFor(passwordLabel);
        GridBagConstraints gbc_passwordLabel = new GridBagConstraints();
        gbc_passwordLabel.anchor = GridBagConstraints.EAST;
        gbc_passwordLabel.insets = new Insets(0, 0, 5, 5);
        gbc_passwordLabel.gridx = 1;
        gbc_passwordLabel.gridy = 6;
        add(passwordLabel, gbc_passwordLabel);
        
        passwordField = new JPasswordField();
        passwordField.setColumns(20);
        GridBagConstraints gbc_passwordField = new GridBagConstraints();
        gbc_passwordField.gridwidth = 4;
        gbc_passwordField.insets = new Insets(0, 0, 5, 5);
        gbc_passwordField.fill = GridBagConstraints.HORIZONTAL;
        gbc_passwordField.gridx = 2;
        gbc_passwordField.gridy = 6;
        add(passwordField, gbc_passwordField);
        
        JButton registerButton = new JButton("Register");
        GridBagConstraints gbc_registerButton = new GridBagConstraints();
        gbc_registerButton.gridwidth = 4;
        gbc_registerButton.insets = new Insets(0, 0, 5, 5);
        gbc_registerButton.gridx = 2;
        gbc_registerButton.gridy = 7;
        add(registerButton, gbc_registerButton);
        registerButton.addActionListener(new RegisterActionListener());
    }
    
    private final class RegisterActionListener implements ActionListener {
        @Override public void actionPerformed(ActionEvent e) {
            String name = nameField.getText().trim();
            String address = addressField.getText().trim();
            String city = cityField.getText().trim();
            String state = stateComboBox.getModel().getSelectedItem().toString();
            String username = usernameField.getText().trim();
            String hashedPassword = DigestUtils.shaHex(new String(passwordField.getPassword()));
            
            int zip;
            try {
                zip = Integer.parseInt(zipField.getText().trim());
                if (zip < 0 || zip > 99999) {
                    throw new NumberFormatException();
                }
            } catch (NumberFormatException nfe) {
                JOptionPane.showMessageDialog(RegisterPanel.this, "Invalid zip code.");
                return;
            }
            
            if (loginDAO.getLogin(username) != null) {
                JOptionPane.showMessageDialog(RegisterPanel.this, "The selected username already exists.");
                return;
            }
            
            Patron patron = new Patron(name, address, city, state, zip);
            patronDAO.insert(patron);
            
            Login login = new Login(username, hashedPassword, patron.getId());
            loginDAO.insert(login);
            
            libraryGUI.login(login);
        }
    }

    @Override
    public void clear() {
        nameField.setText("");
        addressField.setText("");
        cityField.setText("");
        stateComboBox.setSelectedIndex(0);
        zipField.setText("");
        usernameField.setText("");
        passwordField.setText("");
    }
}
